﻿package fr.babos.core.mvc 
{
	import fr.babos.core.bootstrap.IBootstrap;
	import fr.babos.core.errors.BabosError;
	import fr.babos.core.mvc.IView;
	import fr.babos.utils.ObjectUtils;
	import org.osflash.signals.DeluxeSignal;
	import org.osflash.signals.events.GenericEvent;
	import org.osflash.signals.IDispatcher;
	import org.osflash.signals.ISignal;
	
	/**
	 * La classe de base pour les controlleurs
	 * @author ZoulouX
	 */
	public class Controller implements IController
	{
		/**
		 * Si l'objet est démarré
		 */
		protected var _started					:Boolean						= false;
		
		/**
		 * Lorsque l'objet est en train d'être démarré
		 */
		protected var _onTurningOn				:DeluxeSignal					= new DeluxeSignal(this);
		
		/**
		 * Lorsque l'objet est démarré
		 */
		protected var _onTurnedOn				:DeluxeSignal					= new DeluxeSignal(this);
		
		/**
		 * Lorsque l'objet est en train d'être arrêté
		 */
		protected var _onTurningOff				:DeluxeSignal					= new DeluxeSignal(this);
		
		/**
		 * Lorsque l'objet est arrêté
		 */
		protected var _onTurnedOff				:DeluxeSignal					= new DeluxeSignal(this);
		
		
		/**
		 * Les paramètres de la dernière action appelée
		 */
		protected var _params					:Object;
		
		/**
		 * Le bootstrap associé
		 */
		protected var _bootstrap				:IBootstrap;
		
		
		/**
		 * Si l'objet est démarré
		 */
		public function get started ():Boolean { return _started; };
		
		/**
		 * Lorsque l'objet est en train d'être démarré
		 */
		public function get onTurningOn ():ISignal { return _onTurningOn; };
		
		/**
		 * Lorsque l'objet est démarré
		 */
		public function get onTurnedOn ():ISignal { return _onTurnedOn; };
		
		/**
		 * Lorsque l'objet est en train d'être arrêté
		 */
		public function get onTurningOff ():ISignal { return _onTurningOff; };
		
		/**
		 * Lorsque l'objet est arrêté
		 */
		public function get onTurnedOff ():ISignal { return _onTurnedOff; };
		
		
		/**
		 * Les paramètres de la dernière action appelée
		 */
		public function get params ():Object { return _params; };
		public function set params (value:Object):void
		{
			_params = value;
		}
		
		/**
		 * Une référence vers le bootstrap qui a instancié ce controlleur
		 */
		public function get bootstrap ():IBootstrap { return _bootstrap; }
		public function set bootstrap (value:IBootstrap):void
		{
			_bootstrap = value;
		}
		
		
		/**
		 * Le constructeur
		 */
		public function Controller ()
		{
			
		}
		
		
		/**
		 * Dispatcher une notification engine
		 */
		protected function dispatchEngineSignal (pSignal:ISignal):void
		{
			// Dispatcher avec un event
			(pSignal as IDispatcher).dispatch(new GenericEvent());
		}
		
		
		/**
		 * Démarrer l'objet
		 */
		public function turnOn ():void
		{
			// Démarré
			_started = true;
			
			// Dispatcher directement (ne pas faire de super pour comportement différent)
			dispatchEngineSignal(_onTurningOn);
			dispatchEngineSignal(_onTurnedOn);
		}
		
		/**
		 * Arrêter l'objet
		 */
		public function turnOff ():void
		{
			// Arrêté
			_started = false;
			
			// Dispatcher directement (ne pas faire de super pour comportement différent)
			dispatchEngineSignal(_onTurningOff);
			dispatchEngineSignal(_onTurnedOff);
		}
		
		/**
		 * Appeler une action directement sur le controlleur (ne remontera pas le flux vers le bootstrap)
		 * @param	pActionName : Le nom de l'action sur le controlleur
		 * @param	pParams : Les paramètres de l'action
		 */
		public function callAction (pActionName:String, pParams:Object):Boolean
		{
			// Vérifier si l'action est appelable directement
			if (pActionName in this && this[pActionName] is Function)
			{
				// Enregistrer les paramètres
				params = ObjectUtils.extra({}, pParams);
				
				// Appeler l'action
				var r:* = this[pActionName]();
				
				return (r == null ? true : !!r);
			}
			else
			{
				// Déclancher une erreur
				throw new BabosError("Controler.callAction", "Action not found on " + this);
			}
			
			return false;
		}
		
		/**
		 * Appeler une commande sur le bootstrap (si disponible, sinon erreur)
		 * @param	pCommandName : Le nom de la commande a ouvrir sur le bootstrap
		 * @param	pParams : Les paramètres associés à cette commande
		 */
		protected function openCommand (pCommandName:String, pParams:Object = null):void
		{
			// Vérifier si on un bien un bootstrap de navigation
			if (_bootstrap != null)
			{
				// Appeler la commande sur le bootstrap de navigation
				_bootstrap.open(pCommandName, pParams);
			}
			else
			{
				// Déclancher l'erreur
				throw new BabosError("Controller.openCommand", "No bootstrap on " + this);
			}
		}
		
		/**
		 * Une valeur est injectée par un manager de dépendances
		 * @param	pPropertyName : Le nom de la propriété injectée
		 * @param	pInjectedValue : La valeur injectée
		 */
		public function injected (pPropertyName:String, pInjectedValue:*):void
		{
			
		}
		
		/**
		 * Détruire ce controlleur
		 */
		public function dispose ():void
		{
			// Désactiver les signaux
			_onTurningOn.removeAll();
			_onTurnedOn.removeAll();
			_onTurningOff.removeAll();
			_onTurnedOff.removeAll();
			
			// Virer les signaux
			_onTurningOn = null;
			_onTurnedOn = null;
			_onTurningOff = null;
			_onTurnedOff = null;
		}
	}
}